home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / Textfiles / Hacking / UnixCPrograms.sit / UnixCPrograms / solsniffer.c < prev    next >
Text File  |  1997-02-10  |  20KB  |  834 lines

  1. /* solsniffer.c - v1.10 - Michael R. Widner (atreus, J.Galt)
  2.  *
  3.  * This is sunsniffer.c modified to run on dlpi systems, notably
  4.  * solaris 2.x.  The additions are rather verbose, but I'm really
  5.  * too damn lazy to bother cleaning it up.
  6.  
  7.  * 4/26/94 - initial code.  Had some serious hacks in the bufmod stuff.
  8.  * 4/28/94 - v 1.0 fixed up the bufmod stuff a little, but still wrong.
  9.  * 8/11/94 - v 1.1 ok, bufmod fixed.  No more packet dropping.
  10.  *           Also fixed/added some command line options.
  11.  *           -sflt to filter smtp, ftp, login and telnet respectively.
  12.  *           -d x  to set data limit; good for catching mail and stuff
  13.  *            going through firewalls.  Like luser on my subnet does
  14.  *            telnet firewall.myorg.com, then from there does
  15.  *            telnet someplace.outside.mynet
  16.  */
  17.  
  18. #include    <sys/stream.h>
  19. #include    <sys/dlpi.h>
  20. #include    <sys/bufmod.h>
  21.  
  22. #include <stdio.h>
  23. #include <ctype.h>
  24. #include <string.h>
  25.  
  26. #include <sys/time.h>
  27. #include <sys/file.h>
  28. #include <sys/stropts.h>
  29. #include <sys/signal.h>
  30. #include <sys/types.h>
  31. #include <sys/socket.h>
  32. #include <sys/ioctl.h>
  33.  
  34. #include <net/if.h>
  35. #include <net/if_arp.h>
  36.  
  37. #include <netinet/in.h>
  38. #include <netinet/if_ether.h>
  39. #include <netinet/in_systm.h>
  40. #include <netinet/ip.h>
  41. #include <netinet/udp.h>
  42. #include <netinet/ip_var.h>
  43. #include <netinet/udp_var.h>
  44. #include <netinet/in_systm.h>
  45. #include <netinet/tcp.h>
  46. #include <netinet/ip_icmp.h>
  47.  
  48. #include <netdb.h>
  49. #include <arpa/inet.h>
  50.  
  51. /* #define        MAXDLBUF    8192  /* this is much too low -mrw */
  52. #define        MAXDLBUF    32768 /* This is much bigger than any packet */
  53. #define        MAXWAIT        15
  54. #define        MAXDLADDR    1024
  55.  
  56. /* workaround for bcopy, etc. */
  57. #define bcopy(s1, s2, len) memcpy(s2, s1, len)
  58. #define index(s, c) strchr(s, c)
  59. #define rindex(s, c) strrchr(s, c)
  60. #define bzero(s, len) memset(s, 0, len)
  61. #define bcmp(s1, s2, len) (memcmp(s1, s2, len)!=0)
  62. /*
  63.  * externs go here
  64.  */
  65. extern    void    sigalrm();
  66. #define ERR stderr
  67.  
  68. char    *malloc();
  69. char    *device,
  70.         *ProgName,
  71.         *LogName;
  72. FILE    *LOG;
  73. int     debug=0;
  74. long    databuf[MAXDLBUF];
  75.  
  76. #define NIT_DEV     "/dev/le"
  77. #define CHUNKSIZE   4096        /* device buffer size */
  78. int     if_fd = -1;
  79. int     Packet[CHUNKSIZE+32];
  80.  
  81. /* More ugly global stuff. */
  82. int    promisc = 1;    /* promiscuous mode "on" by default */
  83. int    bufmod = 0;        /* push buffer module, "off" by default */
  84. int    filter_flags=0;    /* connections we'd like to fileter */
  85. #define FILT_TELNET  1
  86. #define FILT_FTP     2
  87. #define FILT_LOGIN   4
  88. #define FILT_SMTP    8
  89. int    maxbuflen=128;    /* Define a new DATA LIMIT. Still max at MAXBUFLEN */
  90.  
  91. void Pexit(err,msg)
  92. int err; char *msg;
  93. { perror(msg);
  94.   exit(err); }
  95.  
  96. void Zexit(err,msg)
  97. int err; char *msg;
  98. { fprintf(ERR,msg);
  99.   exit(err); }
  100.  
  101. #define IP          ((struct ip *)Packet)
  102. #define IP_OFFSET   (0x1FFF)
  103. #define SZETH       (sizeof(struct ether_header))
  104. #define IPLEN       (ntohs(ip->ip_len))
  105. #define IPHLEN      (ip->ip_hl)
  106. #define TCPOFF      (tcph->th_off)
  107. #define IPS         (ip->ip_src)
  108. #define IPD         (ip->ip_dst)
  109. #define TCPS        (tcph->th_sport)
  110. #define TCPD        (tcph->th_dport)
  111. #define IPeq(s,t)   ((s).s_addr == (t).s_addr)
  112.  
  113. #define TCPFL(FLAGS) (tcph->th_flags & (FLAGS))
  114.  
  115. /* I cranked this up.  reduce it if you run out of mem. -mrw */ 
  116. #define MAXBUFLEN  (8192)
  117. time_t  LastTIME = 0;
  118.  
  119. struct CREC {
  120.      struct CREC *Next,
  121.                  *Last;
  122.      time_t  Time;              /* start time */
  123.      struct in_addr SRCip,
  124.                     DSTip;
  125.      u_int   SRCport,           /* src/dst ports */
  126.              DSTport;
  127.      u_char  Data[MAXBUFLEN+2]; /* important stuff :-) */
  128.      u_int   Length;            /* current data length */
  129.      u_int   PKcnt;             /* # pkts */
  130.      u_long  LASTseq;
  131. };
  132.  
  133. struct CREC *CLroot = NULL;
  134.  
  135. char *Symaddr(ip)
  136. struct in_addr ip;
  137. { struct hostent *he =
  138.       gethostbyaddr((char *)&ip.s_addr, sizeof(struct in_addr),AF_INET);
  139.  
  140.   return( (he)?(he->h_name):(inet_ntoa(ip)) );
  141. }
  142.  
  143. char *TCPflags(flgs)
  144. register u_char flgs;
  145. { static char iobuf[8];
  146. #define SFL(P,THF,C) iobuf[P]=((flgs & THF)?C:'-')
  147.  
  148.   SFL(0,TH_FIN, 'F');
  149.   SFL(1,TH_SYN, 'S');
  150.   SFL(2,TH_RST, 'R');
  151.   SFL(3,TH_PUSH,'P');
  152.   SFL(4,TH_ACK, 'A');
  153.   SFL(5,TH_URG, 'U');
  154.   iobuf[6]=0;
  155.   return(iobuf);
  156. }
  157.  
  158. char *SERVp(port)
  159. register u_int port;
  160. { static char buf[10];
  161.   register char *p;
  162.  
  163.    switch(port) {
  164.      case IPPORT_LOGINSERVER: p="rlogin"; break;
  165.      case IPPORT_TELNET:      p="telnet"; break;
  166.      case IPPORT_SMTP:        p="smtp"; break;
  167.      case IPPORT_FTP:         p="ftp"; break;
  168.      default: sprintf(buf,"%u",port); p=buf; break;
  169.    }
  170.    return(p);
  171. }
  172.  
  173. char *Ptm(t)
  174. register time_t *t;
  175. { register char *p = ctime(t);
  176.   p[strlen(p)-6]=0; /* strip " YYYY\n" */
  177.   return(p);
  178. }
  179.  
  180. char *NOWtm()
  181. { time_t tm;
  182.   time(&tm);
  183.   return( Ptm(&tm) );
  184. }
  185.  
  186. #define MAX(a,b) (((a)>(b))?(a):(b))
  187. #define MIN(a,b) (((a)<(b))?(a):(b))
  188.  
  189. /* add an item */
  190. #define ADD_NODE(SIP,DIP,SPORT,DPORT,DATA,LEN) { \
  191.   register struct CREC *CLtmp = \
  192.         (struct CREC *)malloc(sizeof(struct CREC)); \
  193.   time( &(CLtmp->Time) ); \
  194.   CLtmp->SRCip.s_addr = SIP.s_addr; \
  195.   CLtmp->DSTip.s_addr = DIP.s_addr; \
  196.   CLtmp->SRCport = SPORT; \
  197.   CLtmp->DSTport = DPORT; \
  198.   CLtmp->Length = MIN(LEN,MAXBUFLEN); \
  199.   bcopy( (u_char *)DATA, (u_char *)CLtmp->Data, CLtmp->Length); \
  200.   CLtmp->PKcnt = 1; \
  201.   CLtmp->Next = CLroot; \
  202.   CLtmp->Last = NULL; \
  203.   CLroot = CLtmp; \
  204. }
  205.  
  206. struct CREC *GET_NODE(Sip,SP,Dip,DP)
  207. struct in_addr Sip,Dip;
  208. register u_int SP,DP;
  209. { struct CREC *CLr = CLroot;
  210.  
  211.   while(CLr != NULL) {
  212.     if( (CLr->SRCport == SP) && (CLr->DSTport == DP) &&
  213.         IPeq(CLr->SRCip,Sip) && IPeq(CLr->DSTip,Dip) )
  214.             break;
  215.     CLr = CLr->Next;
  216.   }
  217.   return(CLr);
  218. }
  219.              
  220. #define ADDDATA_NODE(CL,DATA,LEN) { \
  221.  bcopy((u_char *)DATA, (u_char *)&CL->Data[CL->Length],LEN); \
  222.  CL->Length += LEN; \
  223. }
  224.  
  225. #define PR_DATA(dp,ln) {    \
  226.   register u_char lastc=0; \
  227.   while(ln-- >0) { \
  228.      if(*dp < 32) {  \
  229.         switch(*dp) { \
  230.             case '\0': if((lastc=='\r') || (lastc=='\n') || lastc=='\0') \
  231.                         break; \
  232.             case '\r': \
  233.             case '\n': fprintf(LOG,"\n     : "); \
  234.                         break; \
  235.             default  : fprintf(LOG,"^%c", (*dp + 64)); \
  236.                         break; \
  237.         } \
  238.      } else { \
  239.         if(isprint(*dp)) fputc(*dp,LOG); \
  240.         else fprintf(LOG,"(%d)",*dp); \
  241.      } \
  242.      lastc = *dp++; \
  243.   } \
  244.   fflush(LOG); \
  245. }
  246.  
  247. void END_NODE(CLe,d,dl,msg)
  248. register struct CREC *CLe;
  249. register u_char *d;
  250. register int dl;
  251. register char *msg;
  252. {
  253.    fprintf(LOG,"\n-- TCP/IP LOG -- TM: %s --\n", Ptm(&CLe->Time));
  254.    fprintf(LOG," PATH: %s(%s) =>", Symaddr(CLe->SRCip),SERVp(CLe->SRCport));
  255.    fprintf(LOG," %s(%s)\n", Symaddr(CLe->DSTip),SERVp(CLe->DSTport));
  256.    fprintf(LOG," STAT: %s, %d pkts, %d bytes [%s]\n",
  257.                         NOWtm(),CLe->PKcnt,(CLe->Length+dl),msg);
  258.    fprintf(LOG," DATA: ");
  259.     { register u_int i = CLe->Length;
  260.       register u_char *p = CLe->Data;
  261.       PR_DATA(p,i);
  262.       PR_DATA(d,dl);
  263.     }
  264.  
  265.    fprintf(LOG,"\n-- \n");
  266.    fflush(LOG);
  267.  
  268.    if(CLe->Next != NULL)
  269.     CLe->Next->Last = CLe->Last;
  270.    if(CLe->Last != NULL)
  271.     CLe->Last->Next = CLe->Next;
  272.    else
  273.     CLroot = CLe->Next;
  274.    free(CLe);
  275. }
  276.  
  277. /* 30 mins (x 60 seconds) */
  278. #define IDLE_TIMEOUT 1800
  279. #define IDLE_NODE() { \
  280.   time_t tm; \
  281.   time(&tm); \
  282.   if(LastTIME<tm) { \
  283.      register struct CREC *CLe,*CLt = CLroot; \
  284.      LastTIME=(tm+IDLE_TIMEOUT); tm-=IDLE_TIMEOUT; \
  285.      while(CLe=CLt) { \
  286.        CLt=CLe->Next; \
  287.        if(CLe->Time <tm) \
  288.            END_NODE(CLe,(u_char *)NULL,0,"IDLE TIMEOUT"); \
  289.      } \
  290.   } \
  291. }
  292.  
  293. void filter(cp, pktlen)
  294. register char *cp;
  295. register u_int pktlen;
  296. {
  297.  register struct ip     *ip;
  298.  register struct tcphdr *tcph;
  299.  
  300.  { register u_short EtherType=ntohs(((struct ether_header *)cp)->ether_type);
  301.  
  302.    if(EtherType < 0x600) {
  303.      EtherType = *(u_short *)(cp + SZETH + 6);
  304.      cp+=8; pktlen-=8;
  305.    }
  306.  
  307.    if(EtherType != ETHERTYPE_IP) /* chuk it if its not IP */
  308.       return;
  309.  }
  310.  
  311.     /* ugh, gotta do an alignment :-( */
  312.  bcopy(cp + SZETH, (char *)Packet,(int)(pktlen - SZETH));
  313.  
  314.  ip = (struct ip *)Packet;
  315.  if( ip->ip_p != IPPROTO_TCP) /* chuk non tcp pkts */
  316.     return;
  317.  tcph = (struct tcphdr *)(Packet + IPHLEN);
  318.  
  319. if(!( ((TCPD == IPPORT_TELNET) && !(filter_flags & FILT_TELNET)) ||
  320.        ((TCPD == IPPORT_LOGINSERVER) && !(filter_flags & FILT_LOGIN)) ||
  321.        ((TCPD == IPPORT_FTP) && !(filter_flags & FILT_FTP)) ||
  322.        ((TCPD == IPPORT_SMTP) && !(filter_flags & FILT_SMTP))
  323.    )) return;
  324.  
  325.  { register struct CREC *CLm;
  326.    register int length = ((IPLEN - (IPHLEN * 4)) - (TCPOFF * 4));
  327.    register u_char *p = (u_char *)Packet;
  328.  
  329.    p += ((IPHLEN * 4) + (TCPOFF * 4));
  330.  
  331.  if(debug) {
  332.   fprintf(LOG,"PKT: (%s %04X) ", TCPflags(tcph->th_flags),length);
  333.   fprintf(LOG,"%s[%s] => ", inet_ntoa(IPS),SERVp(TCPS));
  334.   fprintf(LOG,"%s[%s]\n", inet_ntoa(IPD),SERVp(TCPD));
  335.  }
  336.  
  337.    if( CLm = GET_NODE(IPS, TCPS, IPD, TCPD) ) {
  338.  
  339.       CLm->PKcnt++;
  340.  
  341.       if(length>0)
  342.         if( (CLm->Length + length) < maxbuflen ) { /* was MAXBUFLEN */
  343.           ADDDATA_NODE( CLm, p,length);
  344.         } else {
  345.           END_NODE( CLm, p,length, "DATA LIMIT");
  346.         }
  347.  
  348.       if(TCPFL(TH_FIN|TH_RST)) {
  349.           END_NODE( CLm, (u_char *)NULL,0,TCPFL(TH_FIN)?"TH_FIN":"TH_RST" );
  350.       }
  351.  
  352.    } else {
  353.  
  354.       if(TCPFL(TH_SYN)) {
  355.          ADD_NODE(IPS,IPD,TCPS,TCPD,p,length);
  356.       }
  357.  
  358.    }
  359.  
  360.    IDLE_NODE();
  361.  
  362.  }
  363.  
  364. }
  365.  
  366. /* signal handler
  367.  */
  368. void death()
  369. { register struct CREC *CLe;
  370.  
  371.     while(CLe=CLroot)
  372.         END_NODE( CLe, (u_char *)NULL,0, "SIGNAL");
  373.  
  374.     fprintf(LOG,"\nLog ended at => %s\n",NOWtm());
  375.     fflush(LOG);
  376.     if(LOG != stdout)
  377.         fclose(LOG);
  378.     exit(1);
  379. }
  380.  
  381. /* opens network interface, performs ioctls and reads from it,
  382.  * passing data to filter function
  383.  */
  384.  
  385.  
  386. err(fmt, a1, a2, a3, a4)
  387. char    *fmt;
  388. char    *a1, *a2, *a3, *a4;
  389. {
  390.     (void) fprintf(stderr, fmt, a1, a2, a3, a4);
  391.     (void) fprintf(stderr, "\n");
  392.     (void) exit(1);
  393. }
  394.  
  395. static void
  396. sigalrm()
  397. {
  398.     (void) err("sigalrm:  TIMEOUT");
  399. }
  400.  
  401. strgetmsg(fd, ctlp, datap, flagsp, caller)
  402. int    fd;
  403. struct    strbuf    *ctlp, *datap;
  404. int    *flagsp;
  405. char    *caller;
  406. {
  407.     int    rc;
  408.     static    char    errmsg[80];
  409.  
  410.     /*
  411.      * Start timer.
  412.      */
  413.     (void) signal(SIGALRM, sigalrm);
  414.     if (alarm(MAXWAIT) < 0) {
  415.         (void) sprintf(errmsg, "%s:  alarm", caller);
  416.         syserr(errmsg);
  417.     }
  418.  
  419.     /*
  420.      * Set flags argument and issue getmsg().
  421.      */
  422.     *flagsp = 0;
  423.     if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) {
  424.         (void) sprintf(errmsg, "%s:  getmsg", caller);
  425.         syserr(errmsg);
  426.     }
  427.  
  428.     /*
  429.      * Stop timer.
  430.      */
  431.     if (alarm(0) < 0) {
  432.         (void) sprintf(errmsg, "%s:  alarm", caller);
  433.         syserr(errmsg);
  434.     }
  435.  
  436.     /*
  437.      * Check for MOREDATA and/or MORECTL.
  438.      */
  439.     if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA))
  440.         err("%s:  MORECTL|MOREDATA", caller);
  441.     if (rc & MORECTL)
  442.         err("%s:  MORECTL", caller);
  443.     if (rc & MOREDATA)
  444.         err("%s:  MOREDATA", caller);
  445.  
  446.     /*
  447.      * Check for at least sizeof (long) control data portion.
  448.      */
  449.     if (ctlp->len < sizeof (long))
  450.         err("getmsg:  control portion length < sizeof (long):  %d", ctlp->len);
  451. }
  452.  
  453. expecting(prim, dlp)
  454. int    prim;
  455. union    DL_primitives    *dlp;
  456. {
  457.     if (dlp->dl_primitive != (u_long)prim) {
  458.         err("unexpected dlprim error\n");
  459.         exit(1);
  460.     }
  461. }
  462. strioctl(fd, cmd, timout, len, dp)
  463. int    fd;
  464. int    cmd;
  465. int    timout;
  466. int    len;
  467. char    *dp;
  468. {
  469.     struct    strioctl    sioc;
  470.     int    rc;
  471.  
  472.     sioc.ic_cmd = cmd;
  473.     sioc.ic_timout = timout;
  474.     sioc.ic_len = len;
  475.     sioc.ic_dp = dp;
  476.     rc = ioctl(fd, I_STR, &sioc);
  477.  
  478.     if (rc < 0)
  479.         return (rc);
  480.     else
  481.         return (sioc.ic_len);
  482. }
  483. dlattachreq(fd, ppa)
  484. int    fd;
  485. u_long    ppa;
  486. {
  487.     dl_attach_req_t    attach_req;
  488.     struct    strbuf    ctl;
  489.     int    flags;
  490.  
  491.     attach_req.dl_primitive = DL_ATTACH_REQ;
  492.     attach_req.dl_ppa = ppa;
  493.  
  494.     ctl.maxlen = 0;
  495.     ctl.len = sizeof (attach_req);
  496.     ctl.buf = (char *) &attach_req;
  497.  
  498.     flags = 0;
  499.  
  500.     if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
  501.         syserr("dlattachreq:  putmsg");
  502. }
  503.  
  504. dlokack(fd, bufp)
  505. int    fd;
  506. char    *bufp;
  507. {
  508.     union    DL_primitives    *dlp;
  509.     struct    strbuf    ctl;
  510.     int    flags;
  511.  
  512.     ctl.maxlen = MAXDLBUF;
  513.     ctl.len = 0;
  514.     ctl.buf = bufp;
  515.  
  516.     strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack");
  517.  
  518.     dlp = (union DL_primitives *) ctl.buf;
  519.  
  520.     expecting(DL_OK_ACK, dlp);
  521.  
  522.     if (ctl.len < sizeof (dl_ok_ack_t))
  523.         err("dlokack:  response ctl.len too short:  %d", ctl.len);
  524.  
  525.     if (flags != RS_HIPRI)
  526.         err("dlokack:  DL_OK_ACK was not M_PCPROTO");
  527.  
  528.     if (ctl.len < sizeof (dl_ok_ack_t))
  529.         err("dlokack:  short response ctl.len:  %d", ctl.len);
  530. }
  531.  
  532.  
  533. dlbindreq(fd, sap, max_conind, service_mode, conn_mgmt, xidtest)
  534. int    fd;
  535. u_long    sap;
  536. u_long    max_conind;
  537. u_long    service_mode;
  538. u_long    conn_mgmt;
  539. u_long    xidtest;
  540. {
  541.     dl_bind_req_t    bind_req;
  542.     struct    strbuf    ctl;
  543.     int    flags;
  544.  
  545.     bind_req.dl_primitive = DL_BIND_REQ;
  546.     bind_req.dl_sap = sap;
  547.     bind_req.dl_max_conind = max_conind;
  548.     bind_req.dl_service_mode = service_mode;
  549.     bind_req.dl_conn_mgmt = conn_mgmt;
  550.     bind_req.dl_xidtest_flg = xidtest;
  551.  
  552.     ctl.maxlen = 0;
  553.     ctl.len = sizeof (bind_req);
  554.     ctl.buf = (char *) &bind_req;
  555.  
  556.     flags = 0;
  557.  
  558.     if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
  559.         syserr("dlbindreq:  putmsg");
  560. }
  561.  
  562. dlbindack(fd, bufp)
  563. int    fd;
  564. char    *bufp;
  565. {
  566.     union    DL_primitives    *dlp;
  567.     struct    strbuf    ctl;
  568.     int    flags;
  569.  
  570.     ctl.maxlen = MAXDLBUF;
  571.     ctl.len = 0;
  572.     ctl.buf = bufp;
  573.  
  574.     strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlbindack");
  575.  
  576.     dlp = (union DL_primitives *) ctl.buf;
  577.  
  578.     expecting(DL_BIND_ACK, dlp);
  579.  
  580.     if (flags != RS_HIPRI)
  581.         err("dlbindack:  DL_OK_ACK was not M_PCPROTO");
  582.  
  583.     if (ctl.len < sizeof (dl_bind_ack_t))
  584.         err("dlbindack:  short response ctl.len:  %d", ctl.len);
  585. }
  586.  
  587. dlpromisconreq(fd, level)
  588. int    fd;
  589. u_long    level;
  590. {
  591.     dl_promiscon_req_t    promiscon_req;
  592.     struct    strbuf    ctl;
  593.     int    flags;
  594.  
  595.     promiscon_req.dl_primitive = DL_PROMISCON_REQ;
  596.     promiscon_req.dl_level = level;
  597.  
  598.     ctl.maxlen = 0;
  599.     ctl.len = sizeof (promiscon_req);
  600.     ctl.buf = (char *) &promiscon_req;
  601.  
  602.     flags = 0;
  603.  
  604.     if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0)
  605.         syserr("dlpromiscon:  putmsg");
  606.  
  607. }
  608.  
  609. syserr(s)
  610. char    *s;
  611. {
  612.     (void) perror(s);
  613.     exit(1);
  614. }
  615.  
  616.  
  617. do_it()
  618. {
  619.     long    buf[MAXDLBUF];
  620.     char    *device;
  621.     int    ppa;
  622.     int    fd;
  623.     int    sap;
  624.     struct    strbuf    data;
  625.     int    flags;
  626.     int    i;
  627.     int    c;
  628.     int    offset;
  629.     int    len;
  630.     struct    timeval    t;
  631.     u_int    chunksize = 16 * 1024;
  632.     struct    sb_hdr    *bp;
  633.     char    *p, *limp;
  634.  
  635.     int mrwtmp; /* temporary debugging crap */
  636.  
  637.     device = "/dev/le";
  638.     ppa = 0;
  639.     sap= 0x800;
  640.  
  641.     /*
  642.      * Open the device.
  643.      */
  644.     if ((fd = open(device, 2)) < 0)
  645.         syserr(device);
  646.  
  647.     /*
  648.      * Attach.
  649.      */
  650.     dlattachreq(fd, ppa);
  651.     dlokack(fd, buf);
  652.  
  653.     /*
  654.      * Optionally enable promiscuous mode.
  655.      */
  656.     if (promisc) {
  657.         dlpromisconreq(fd, DL_PROMISC_PHYS);
  658.         dlokack(fd, buf);
  659.     }
  660.  
  661.     /*
  662.      * Bind.
  663.      */
  664.     dlbindreq(fd, sap, 0, DL_CLDLS, 0, 0);
  665.     dlbindack(fd, buf);
  666.  
  667.     /*
  668.      * Issue DLIOCRAW ioctl.
  669.      */
  670.     if (strioctl(fd, DLIOCRAW, -1, 0, NULL) < 0)
  671.         syserr("DLIOCRAW");
  672.  
  673.     /*
  674.      * Push and configure buffer module.
  675.      */
  676.     if (bufmod) {
  677.         if (ioctl(fd, I_PUSH, "bufmod") < 0)
  678.             syserr("push bufmod");
  679.  
  680.         t.tv_sec = 0;
  681.         t.tv_usec = 500000;    /* 0.5s */
  682.         if (strioctl(fd, SBIOCSTIME, -1, sizeof (struct timeval),
  683.             &t) < 0)
  684.             syserr("SBIOCSTIME");
  685.         if (strioctl(fd, SBIOCSCHUNK, -1, sizeof (u_int),
  686.             &chunksize) < 0)
  687.             syserr("SBIOCSCHUNK");
  688.     }
  689.  
  690.     /*
  691.      * Flush the read side of the Stream.
  692.      */
  693.     if (ioctl(fd, I_FLUSH, FLUSHR) < 0)
  694.         syserr("I_FLUSH");
  695.  
  696.     /*
  697.      * Read packets.
  698.      */
  699.  
  700.     data.buf = (char *) databuf;
  701.     data.maxlen = MAXDLBUF;
  702.     data.len = 0;
  703.  
  704.     /* Here's the deal:  I had some problems with the bufmod code, but
  705.        I think it's working now.  I don't know a whole lot about the
  706.        whole DLPI interface, so I can't be sure there aren't any
  707.        oversights here.  It seems to be working now, but I have not had
  708.        the time to do extensive testing.
  709.        I know for certain that packets will be dropped on a busy network
  710.        if I don't use bufmod.  That problem should not occur when using
  711.        bufmod, but like I said, I may have overlooked something. */
  712.  
  713.     while (((mrwtmp=getmsg(fd, NULL, &data, &flags))==0) ||
  714.          (mrwtmp==MOREDATA) || (mrwtmp=MORECTL)) {
  715.         p = data.buf;
  716.         limp = p + data.len;
  717.  
  718.     /* This is the ugliest piece of commented out crap that I've ever
  719.        done.  Ignore it.  Someday it will go away. */
  720.     /*    if (data.len && bufmod) {
  721.             for (; p < limp; p += bp->sbh_totlen) {
  722.                 bp = (struct sb_hdr*) p; 
  723.                 /* Display hex data if we want * /
  724.                  for (i = 0; i < bp->sbh_msglen; i++)
  725.                     printf("%02x ", *(p +
  726.                         sizeof (struct sb_hdr) + i)
  727.                         & 0xff);
  728.                 printf("\n"); 
  729.                 filter(p, bp->sbh_msglen);
  730.             } 
  731.         } else if (data.len) { */
  732.             filter(data.buf, data.len); 
  733.         /*    }  else if */
  734.         data.len = 0;
  735.     } /* while */
  736.     printf("finished getmsg() = %i\n",mrwtmp);
  737. }
  738.  
  739.  
  740. /* Authorization, if you'd like it. */
  741. #define AUTHPASSWD "c6Lqd3Dvn2l3s" 
  742.  
  743. void getauth()
  744. { char *buf,*getpass(),*crypt();
  745.   char pwd[21],prmpt[81];
  746.  
  747.     strcpy(pwd,AUTHPASSWD);
  748.     sprintf(prmpt,"(%s)UP? ",ProgName);
  749.     buf=getpass(prmpt);
  750.     if(strcmp(pwd,crypt(buf,pwd)))
  751.         exit(1);
  752. }
  753.      
  754. void main(argc, argv)
  755. int argc;
  756. char **argv;
  757. {
  758.     char   cbuf[BUFSIZ];
  759.     struct ifconf ifc;
  760.     int    s,
  761.            ac=1,
  762.            backg=0;
  763.  
  764.     ProgName=argv[0];
  765.  
  766. /*    getauth(); */
  767. /* I put this here for a reason, but now I'm commenting it out. */
  768. /*    if(!(LOG=fopen((LogName=".tfile"),"a")))
  769.          Zexit(1,"Output file cant be opened\n"); */
  770.  
  771. /* Its still called NIT_DEV, even if it's no longer /dev/nit */
  772.     device=NIT_DEV; 
  773.     while((ac<argc) && (argv[ac][0] == '-')) {
  774.        register char ch = argv[ac++][1];
  775.        switch(toupper(ch)) {
  776.             case 'I': device=argv[ac++];
  777.                       break;
  778.             case 'O': if(!(LOG=fopen((LogName=argv[ac++]),"a")))
  779.                          Zexit(1,"Output file cant be opened\n");
  780.                       break;
  781.             case 'B': backg=1;
  782.                       break;
  783.             case 'S': filter_flags|=FILT_SMTP;
  784.               fprintf(ERR,"filtering out smtp connections.\n");
  785.                       break;
  786.             case 'T': filter_flags|=FILT_TELNET;
  787.               fprintf(ERR,"filtering out telnet connections.\n");
  788.                       break;
  789.             case 'L': filter_flags|=FILT_LOGIN;
  790.               fprintf(ERR,"filtering out rsh/rlogin connections.\n");
  791.                       break;
  792.             case 'F': filter_flags|=FILT_FTP;
  793.               fprintf(ERR,"filtering out ftp connections.\n");
  794.                       break; 
  795.             case 'D': maxbuflen=atoi(argv[ac++]);
  796.               if (maxbuflen > MAXBUFLEN) maxbuflen=MAXBUFLEN;
  797.                       break;
  798.             default : fprintf(ERR,
  799.                         "Usage: %s [-d x] [-s] [-f] [-l] [-t] [-i interface] [-o file]\n",
  800.                             ProgName);
  801.         fprintf(ERR,"    -d int    set new data limit (128 default)\n");
  802.         fprintf(ERR,"    -s        filter out smtp connections\n");
  803.         fprintf(ERR,"    -f        filter out ftp connections\n");
  804.         fprintf(ERR,"    -l        filter out rlogin/rsh connections\n");
  805.         fprintf(ERR,"    -t        filter out telnet connections\n");
  806.         fprintf(ERR,"    -o <file> output to <file>\n");
  807.                       exit(1);
  808.        }
  809.     }
  810.  
  811.     fprintf(ERR,"Using logical device %s [%s]\n",device,NIT_DEV);
  812.     fprintf(ERR,"Output to %s.%s%s",(LOG)?LogName:"stdout",
  813.             (debug)?" (debug)":"",(backg)?" Backgrounding ":"\n");
  814.  
  815.     if(!LOG)
  816.         LOG=stdout;
  817.  
  818.     signal(SIGINT, death);
  819.     signal(SIGTERM,death);
  820.     signal(SIGKILL,death);
  821.     signal(SIGQUIT,death);
  822.  
  823.     if(backg && debug) {
  824.          fprintf(ERR,"[Cannot bg with debug on]\n");
  825.          backg=0;
  826.     }
  827.  
  828.     fprintf(LOG,"\nLog started at => %s [pid %d]\n",NOWtm(),getpid());
  829.     fflush(LOG);
  830.  
  831.     do_it();
  832. }
  833.  
  834.